﻿#include "singlechaanle.h"
#include "ui_singlechaanle.h"

SingleChaanle::SingleChaanle(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::SingleChaanle),
    RubBand(new QRubberBand(QRubberBand::Rectangle, this)),
    Xup(0),
    Xdown(500),
    Yup(100),
    Ydown(-100),
    xPos(0),
    xPosValue(2),
    yPosValue(2)
{
    ui->setupUi(this);
    Init();
}

SingleChaanle::~SingleChaanle()
{
    RubBand->deleteLater();
    delete ui;
}

void SingleChaanle::Init()
{
    QSharedPointer<QCPAxisTicker> yTicker(new QCPAxisTicker);
    yTicker->setTickCount(4);
    ui->Plot->yAxis->setTicker(yTicker);
    ui->Plot->yAxis->setRange(Yup, Ydown);
    ui->Plot->xAxis->setRange(Xup, Xdown);
    ui->Plot->addGraph();
    ui->Plot->graph(0)->setPen(QPen(Qt::blue));
    ui->Plot->addGraph();
    ui->Plot->graph(1)->setPen(QPen(Qt::red));
    ui->Plot->setContextMenuPolicy(Qt::CustomContextMenu);
    connect(ui->Plot, SIGNAL(mousePress(QMouseEvent*)), this, SLOT(mousePressEvent(QMouseEvent*)));
    connect(ui->Plot, SIGNAL(mouseMove(QMouseEvent*)), this, SLOT(mouseMoveEvent(QMouseEvent*)));
    connect(ui->Plot, SIGNAL(mouseRelease(QMouseEvent*)), this, SLOT(mouseReleaseEvent(QMouseEvent*)));
    connect(ui->Plot, SIGNAL(selectionChangedByUser()), this, SLOT(selectionChanged()));
    ui->Plot->setSelectionTolerance(1);
    ui->Plot->selectionRect()->setPen(QPen(Qt::red));
    // 需要选中曲线时，QCP::iSelectPlottables必须要加上
//    ui->Plot->setInteractions(QCP::iSelectAxes | QCP::iSelectLegend | QCP::iSelectPlottables);
    ui->Plot->rescaleAxes();
    ui->Plot->replot();
    this->setLayout(ui->hLayoutMain);
    ui->hLayoutMain->setStretch(0, 2);
    ui->hLayoutMain->setStretch(1, 87);
    ui->hLayoutMain->setStretch(2, 10);
}

QString SingleChaanle::GetWaveInfo(const ChWaveInfo& Info)
{
    return QString("Ch:%1\nFreq:%2\nTime:%3\nValue:%4").
            arg(Info.ChNumber).
            arg(static_cast<double>(Info.Frequency)).
            arg(static_cast<double>(Info.SampTime)).
            arg(Info.Value);
}

void SingleChaanle::SetxAxisRange(double lower, double upper)
{
    Xdown = lower;
    Xup = upper;
}

void SingleChaanle::SetyAxisRange(double lower, double upper)
{
    Ydown = lower;
    Yup = upper;
}

void SingleChaanle::SetData(const QVector<double> &xValue, const QVector<double> &yValue)
{
    ui->Plot->xAxis->setRange(Xdown, Xup);
    ui->Plot->yAxis->setRange(Ydown, Yup);
    ui->Plot->graph(0)->setData(xValue, yValue);
    ui->Plot->replot();
}

void SingleChaanle::on_Plot_customContextMenuRequested(const QPoint &pos)
{
    qDebug() << pos;
}

void SingleChaanle::mousePressEvent(QMouseEvent *e)
{
    if(!ui->Plot->viewport().contains(e->pos())) return;
    switch (e->button()) {
    case Qt::LeftButton:
    {
        if(!RubBand->isVisible()) {
            StartPoint.setX(static_cast<int>(e->pos().x() + 0.5f));
            // Y轴全部
            StartPoint.setY(0);
            RubBand->setGeometry(QRect(StartPoint, QSize()));
            RubBand->show();
        }
        if (ui->Plot->xAxis->selectedParts().testFlag(QCPAxis::spAxis))
            ui->Plot->axisRect()->setRangeDrag(ui->Plot->xAxis->orientation());
        else if (ui->Plot->yAxis->selectedParts().testFlag(QCPAxis::spAxis))
            ui->Plot->axisRect()->setRangeDrag(ui->Plot->yAxis->orientation());
        else
            ui->Plot->axisRect()->setRangeDrag(Qt::Horizontal|Qt::Vertical);
    }
        break;
    case Qt::MidButton:
    {
        ui->Plot->xAxis->setRange(Xdown, Xup);
//        ui->Plot->rescaleAxes();
        ui->Plot->replot();
    }
        break;
    case Qt::RightButton:
    {
        RubBand->hide();
    }
        break;
    default:
        break;
    }
}

void SingleChaanle::mouseMoveEvent(QMouseEvent *e)
{
    if(!ui->Plot->viewport().contains(e->pos())) return;
    if(RubBand->isVisible()) {
        QPoint EndPoint;
        EndPoint.setX(static_cast<int>(e->pos().x() + 0.5f));
        EndPoint.setY(static_cast<int>(e->pos().y() + 0.5f));
        EndPoint.setY(ui->Plot->height());
        RubBand->setGeometry(QRect(StartPoint, EndPoint).normalized());
    }
}

void SingleChaanle::mouseReleaseEvent(QMouseEvent *e)
{
    if(!ui->Plot->viewport().contains(e->pos())) return;
    if(e->button() == Qt::LeftButton) {
        const QRect zoomRect = RubBand->geometry();
        int xp1, yp1, xp2, yp2;
        zoomRect.getCoords(&xp1, &yp1, &xp2, &yp2);
        xPos = static_cast<int>(ui->Plot->xAxis->pixelToCoord(xp1) + static_cast<double>(0.5f));
        double x2 = static_cast<int>(ui->Plot->xAxis->pixelToCoord(xp2) + static_cast<double>(0.5f));
        if(x2 - xPos > 1) {
            // 放大选中区域波形，改变x轴范围
            ui->Plot->xAxis->setRange(xPos, x2);
        }
        else {
            // 到时线
//            QVector<double> x(2), y(2);
//            QRect view = ui->Plot->viewport();
//            QCPAxisRect* size = ui->Plot->axisRect();
            xPosValue[0] = xPos;
            xPosValue[1] = xPos;
            yPosValue[0] = Yup;
            yPosValue[1] = Ydown;
            ui->Plot->graph(1)->setData(xPosValue, yPosValue);
            WaveInfo.SampTime = static_cast<float>(xPosValue[0]);
            WaveInfo.Value = ui->Plot->graph(0)->data()->at(static_cast<int>(xPosValue[0]))->mainValue();
            ui->WaveInfo->setText(GetWaveInfo(WaveInfo));
        }
        ui->Plot->replot();
        RubBand->hide();
    }
}

void SingleChaanle::keyPressEvent(QKeyEvent* e)
{
    switch (e->key()) {
    case Qt::Key_Left:
    {
        if(xPos <= 0)
            break;
        --xPos;
        xPosValue[0] = xPos;
        xPosValue[1] = xPos;
        ui->Plot->graph(1)->setData(xPosValue, yPosValue);
        WaveInfo.SampTime = static_cast<float>(xPosValue[0]);
        WaveInfo.Value = ui->Plot->graph(0)->data()->at(static_cast<int>(xPosValue[0]))->mainValue();
        ui->WaveInfo->setText(GetWaveInfo(WaveInfo));
        ui->Plot->replot();
        break;
    }
    case Qt::Key_Right:
    {
        if(Xup -  xPos <= 0)
            break;
        ++xPos;
        xPosValue[0] = xPos;
        xPosValue[1] = xPos;
        ui->Plot->graph(1)->setData(xPosValue, yPosValue);
        WaveInfo.SampTime = static_cast<float>(xPosValue[0]);
        WaveInfo.Value = ui->Plot->graph(0)->data()->at(static_cast<int>(xPosValue[0]))->mainValue();
        ui->WaveInfo->setText(GetWaveInfo(WaveInfo));
        ui->Plot->replot();
        break;
    }
    default:
        break;
    }
}

void SingleChaanle::selectionChanged()
{
    /*
     normally, axis base line, axis tick labels and axis labels are selectable separately, but we want
     the user only to be able to select the axis as a whole, so we tie the selected states of the tick labels
     and the axis base line together. However, the axis label shall be selectable individually.

     The selection state of the left and right axes shall be synchronized as well as the state of the
     bottom and top axes.

     Further, we want to synchronize the selection of the graphs with the selection state of the respective
     legend item belonging to that graph. So the user can select a graph by either clicking on the graph itself
     or on its legend item.
    */

    // make top and bottom axes be selected synchronously, and handle axis and tick labels as one selectable object:
    if (ui->Plot->xAxis->selectedParts().testFlag(QCPAxis::spAxis) || ui->Plot->xAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||
        ui->Plot->xAxis2->selectedParts().testFlag(QCPAxis::spAxis) || ui->Plot->xAxis2->selectedParts().testFlag(QCPAxis::spTickLabels)) {
        ui->Plot->xAxis2->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
        ui->Plot->xAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
    }
    // make left and right axes be selected synchronously, and handle axis and tick labels as one selectable object:
    if (ui->Plot->yAxis->selectedParts().testFlag(QCPAxis::spAxis) || ui->Plot->yAxis->selectedParts().testFlag(QCPAxis::spTickLabels) ||
        ui->Plot->yAxis2->selectedParts().testFlag(QCPAxis::spAxis) || ui->Plot->yAxis2->selectedParts().testFlag(QCPAxis::spTickLabels)) {
        ui->Plot->yAxis2->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
        ui->Plot->yAxis->setSelectedParts(QCPAxis::spAxis|QCPAxis::spTickLabels);
    }
    // synchronize selection of graphs with selection of corresponding legend items:
    for (int i=0; i<ui->Plot->graphCount(); ++i) {
        QCPGraph *graph = ui->Plot->graph(i);
        QCPPlottableLegendItem *item = ui->Plot->legend->itemWithPlottable(graph);
        if (item->selected() || graph->selected()) {
            item->setSelected(true);
            graph->setSelection(QCPDataSelection(graph->data()->dataRange()));
        }
    }
}
